package com.wang.tool.monitor.fastover;

import com.wang.tool.common.Pair;

/**
 * 快速结束模型
 * 1.抛异常
 * 2.返回指定结果,这是需要处理是否与所需类型匹配
 * 如何解析?
 * 1.if(getFail()!=null) then throw getFail(); 非空代表要抛异常
 * 2.Pair<Boolean,T> pair = fitResult(目标返回类型);
 * 3.if(pair.getLeft()==true) then return  pair.getRight(); else 正常执行逻辑
 *
 * @author shaopeng
 * @date 2023/3/9
 * @see FastoverInfo#resultIsFit
 */
public class FastoverInfo {

    /**
     * 异常
     */
    private Throwable fail;

    /**
     * 快速返回的对象
     */
    private Object result;

    private FastoverInfo() {
    }

    /**
     * 快速抛异常
     *
     * @param error
     * @return
     */
    public static FastoverInfo fastFail(Throwable error) {
        FastoverInfo fastover = new FastoverInfo();
        fastover.setFail(error);
        return fastover;
    }

    /**
     * 快速返回
     *
     * @param result
     * @return
     */
    public static FastoverInfo fastReturn(Object result) {
        FastoverInfo fastover = new FastoverInfo();
        fastover.setResult(result);
        return fastover;
    }

    /**
     * 结果是否拟合目标类型
     *
     * @param pointType 目标类型
     * @param <T>
     * @return 非空
     */
    public <T> Pair<Boolean, T> resultIsFit(Class<T> pointType) {
        if (result == null) {
            //非基础类型 || void,直接返回null
            if (!pointType.isPrimitive() || pointType.equals(void.class)) {
                return new Pair<>(true, null);
            }

            //适配基础类型
            if (pointType.equals(int.class)) {
                return new Pair(true, 0);
            }
            if (pointType.equals(boolean.class)) {
                return new Pair(true, false);
            }
            if (pointType.equals(long.class)) {
                return new Pair(true, 0L);
            }
            if (pointType.equals(double.class)) {
                return new Pair(true, 0.0D);
            }
            if (pointType.equals(byte.class)) {
                return new Pair(true, (byte) 0);
            }
            if (pointType.equals(short.class)) {
                return new Pair(true, (short) 0);
            }
            if (pointType.equals(float.class)) {
                return new Pair(true, 0.0F);
            }
            if (pointType.equals(char.class)) {
                return new Pair(true, '\u0000');
            }
            return new Pair<>(false, null);
        }

        Class<?> realType = result.getClass();
        //下游类
        if (pointType.isAssignableFrom(realType)) {
            return new Pair(true, result);
        }

        //简单对象互为包装
        if (realType.equals(Integer.class)) {
            boolean fit = pointType.equals(int.class) || pointType.equals(Integer.class);
            return new Pair(fit, fit ? result : null);
        }
        if (realType.equals(Boolean.class)) {
            boolean fit = pointType.equals(boolean.class) || pointType.equals(Boolean.class);
            return new Pair(fit,  fit ? result : null);
        }
        if (realType.equals(Long.class)) {
            boolean fit = pointType.equals(long.class) || pointType.equals(Long.class);
            return new Pair(fit,  fit ? result : null);
        }
        if (realType.equals(Double.class)) {
            boolean fit = pointType.equals(double.class) || pointType.equals(Double.class);
            return new Pair(fit,  fit ? result : null);
        }
        if (realType.equals(Byte.class)) {
            boolean fit = pointType.equals(byte.class) || pointType.equals(Byte.class);
            return new Pair(fit,  fit ? result : null);
        }
        if (realType.equals(Short.class)) {
            boolean fit = pointType.equals(short.class) || pointType.equals(Short.class);
            return new Pair(fit,  fit ? result : null);
        }
        if (realType.equals(Float.class)) {
            boolean fit = pointType.equals(float.class) || pointType.equals(Float.class);
            return new Pair(fit,  fit ? result : null);
        }
        if (realType.equals(Character.class)) {
            boolean fit = pointType.equals(char.class) || pointType.equals(Character.class);
            return new Pair(fit,  fit ? result : null);
        }
        return new Pair(false, null);
    }


    public Throwable getFail() {
        return fail;
    }

    public void setFail(Throwable fail) {
        this.fail = fail;
    }


    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "FastoverInfo{" +
                "fail=" + fail +
                ", result=" + result +
                '}';
    }
}
